/*
 * hw.c
 *
 *  Created on: 2018-5-5
 *      Author: chenss
 */


#include "hw.h"

#include "stimer.h"

static const struct _Exti
{
    EXTI_Pin_TypeDef epin;
    EXTI_IT_TypeDef  eit;
} _extis[] =
{
        {EXTI_Pin_0, EXTI_IT_Pin0},
        {EXTI_Pin_1, EXTI_IT_Pin1},
        {EXTI_Pin_2, EXTI_IT_Pin2},
        {EXTI_Pin_6, EXTI_IT_Pin6},
        {EXTI_Pin_4, EXTI_IT_Pin4},
        {EXTI_Pin_3, EXTI_IT_Pin3}
};

static const struct
{
    GPIO_TypeDef *port;
    GPIO_Pin_TypeDef pin;
    HW_Level_t activeLevel;
    const struct _Exti *pexti;
} _ins[] =
{
        {GPIOG, GPIO_Pin_0, HW_Level_Low, & _extis[0]},  // HW_In_Mode,
        {GPIOG, GPIO_Pin_1, HW_Level_Low, & _extis[1]},  // HW_In_Fwd,
        {GPIOG, GPIO_Pin_2, HW_Level_Low, & _extis[2]},  // HW_In_Bwd,
        {GPIOE, GPIO_Pin_6, HW_Level_Low, & _extis[3]},  // HW_In_History,
        {GPIOC, GPIO_Pin_4, HW_Level_Low, & _extis[4]},  // HW_In_Time,
        {GPIOC, GPIO_Pin_3, HW_Level_Low, & _extis[5]},  // HW_In_Search
};

static const struct
{
    GPIO_TypeDef *port;
    GPIO_Pin_TypeDef pin;
    HW_Level_t activeLevel;
    HW_Status_t defaultStatus;
}_outs[] =
{
        {GPIOD, GPIO_Pin_6, HW_Level_High,  HW_Status_Disable},  // HW_Out_Led
        {GPIOD, GPIO_Pin_7, HW_Level_High,  HW_Status_Disable},  // HW_Out_Beep
};

void HW_Init(void)
{
    uint8_t i;
    HW_Level_t level;
    GPIO_Mode_TypeDef mode;

    for(i = 0; i < ARRAY_SIZE(_ins); i++)
    {
        if(_ins[i].pexti)
        {
            GPIO_Init(_ins[i].port, _ins[i].pin, GPIO_Mode_In_PU_IT);
            EXTI_ClearITPendingBit(_ins[i].pexti->eit);
            EXTI_SetPinSensitivity(_ins[i].pexti->epin, EXTI_Trigger_Rising_Falling);
        }
        else
        {
            GPIO_Init(_ins[i].port, _ins[i].pin, GPIO_Mode_In_PU_No_IT);
        }
    }

    for(i = 0; i < ARRAY_SIZE(_outs); i++)
    {
        level = _outs[i].defaultStatus ? _outs[i].activeLevel : ! _outs[i].activeLevel;
        mode = level ? GPIO_Mode_Out_PP_High_Slow : GPIO_Mode_Out_PP_Low_Slow;
        GPIO_Init(_outs[i].port, _outs[i].pin, mode);
    }
}

void HW_Set(HW_Out_t out, HW_Level_t level)
{
    GPIO_WriteBit(_outs[out].port, _outs[out].pin, level);
}

void HW_Config(HW_Out_t out, HW_Status_t status)
{
    HW_Level_t level;

    level = status ? _outs[out].activeLevel : ! _outs[out].activeLevel;
    HW_Set(out, level);
}

void HW_Trigger(HW_Out_t out)
{
    GPIO_ToggleBits(_outs[out].port, _outs[out].pin);
}

HW_Level_t HW_Get(HW_In_t in)
{
    BitStatus stat;

    stat = GPIO_ReadInputDataBit(_ins[in].port, _ins[in].pin);
    return (stat == RESET) ? HW_Level_Low : HW_Level_High;
}

void HW_FlashLed(void)
{
	HW_Config(HW_Out_Led, HW_Status_Enable);
	STimer_Delay(10);
	HW_Config(HW_Out_Led, HW_Status_Disable);
}

int HW_IsEnable(HW_In_t in)
{
    HW_Level_t level;

    level = HW_Get(in);
    return (level == _ins[in].activeLevel) ? HW_Status_Enable : HW_Status_Disable;
}

void HW_ExtiIrs(void)
{
    TASK_SET(TASK_Id_KeyScan);
}

